<template>
  <div class="snake-game">
    <div class="score-board">得分：{{ score }}</div>
    <canvas ref="gameCanvas" :width="canvasWidth" :height="canvasHeight"></canvas>
    <div v-if="gameOver" class="game-over">
      <div>游戏结束！</div>
      <div>按回车键重新开始</div>
    </div>
    <div class="controls">
      <button @click="pauseGame" :disabled="gameOver">暂停</button>
      <button @click="endGame" :disabled="gameOver">结束游戏</button>
    </div>
  </div>
</template>

<script>
export default {
  name: "SnakeGame",
  data() {
    return {
      // Canvas dimensions
      canvasWidth: 400,
      canvasHeight: 400,
      cellSize: 20,

      // Snake properties
      snake: [{ x: 200, y: 200 }],
      direction: { x: 0, y: 0 },

      // Food properties
      food: { x: 0, y: 0 },

      // Game state
      score: 0,
      gameInterval: null,
      gameOver: false,
      isPaused: false,
    };
  },
  mounted() {
    this.resetFood();
    this.startGame();
    window.addEventListener("keydown", this.handleKeydown);
  },
  beforeDestroy() {
    this.stopGame();
    window.removeEventListener("keydown", this.handleKeydown);
  },
  methods: {
    startGame() {
      // 调整游戏更新速度为 200ms，使游戏速度更适中
      this.gameInterval = setInterval(this.updateGame, 200);
    },
    stopGame() {
      clearInterval(this.gameInterval);
    },
    updateGame() {
      if (this.isPaused || this.gameOver) return;

      const head = { ...this.snake[0] };
      head.x += this.direction.x * this.cellSize;
      head.y += this.direction.y * this.cellSize;

      if (this.checkCollision(head)) {
        this.gameOver = true;
        return;
      }

      this.snake.unshift(head);

      if (head.x === this.food.x && head.y === this.food.y) {
        this.score++;
        this.resetFood();
      } else {
        this.snake.pop();
      }

      this.draw();
    },
    draw() {
      const ctx = this.$refs.gameCanvas.getContext("2d");
      ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

      // Draw grid background
      ctx.fillStyle = "#f0f0f0";
      for (let x = 0; x < this.canvasWidth; x += this.cellSize) {
        for (let y = 0; y < this.canvasHeight; y += this.cellSize) {
          ctx.fillRect(x, y, this.cellSize, this.cellSize);
        }
      }

      // Draw snake
      ctx.fillStyle = "rgba(0, 255, 0, 0.8)";
      this.snake.forEach((segment) => {
        ctx.fillRect(segment.x, segment.y, this.cellSize, this.cellSize);
        ctx.strokeStyle = "rgba(0, 255, 0, 0.5)";
        ctx.strokeRect(segment.x, segment.y, this.cellSize, this.cellSize);
      });

      // Draw food
      ctx.fillStyle = "rgba(255, 0, 0, 0.8)";
      ctx.fillRect(this.food.x, this.food.y, this.cellSize, this.cellSize);
      ctx.strokeStyle = "rgba(255, 0, 0, 0.5)";
      ctx.strokeRect(this.food.x, this.food.y, this.cellSize, this.cellSize);
    },
    resetFood() {
      this.food.x = Math.floor(Math.random() * (this.canvasWidth / this.cellSize)) * this.cellSize;
      this.food.y = Math.floor(Math.random() * (this.canvasHeight / this.cellSize)) * this.cellSize;
    },
    resetGame() {
      this.snake = [{ x: 200, y: 200 }];
      this.direction = { x: 0, y: 0 };
      this.score = 0;
      this.gameOver = false;
      this.isPaused = false;
      this.resetFood();
      this.startGame();
    },
    pauseGame() {
      this.isPaused = !this.isPaused;
    },
    endGame() {
      this.gameOver = true;
      this.stopGame();
    },
    handleKeydown(event) {
      const keyPressed = event.keyCode;
      const goingUp = this.direction.y === -1;
      const goingDown = this.direction.y === 1;
      const goingRight = this.direction.x === 1;
      const goingLeft = this.direction.x === -1;

      switch (keyPressed) {
        case 37: // Left arrow key
          if (!goingRight) this.direction = { x: -1, y: 0 };
          break;
        case 38: // Up arrow key
          if (!goingDown) this.direction = { x: 0, y: -1 };
          break;
        case 39: // Right arrow key
          if (!goingLeft) this.direction = { x: 1, y: 0 };
          break;
        case 40: // Down arrow key
          if (!goingUp) this.direction = { x: 0, y: 1 };
          break;
        case 13: // Enter key
          if (this.gameOver) this.resetGame();
          break;
      }
    },
    checkCollision(head) {
      if (
        head.x < 0 ||
        head.x >= this.canvasWidth ||
        head.y < 0 ||
        head.y >= this.canvasHeight
      ) {
        return true;
      }

      for (let i = 1; i < this.snake.length; i++) {
        if (head.x === this.snake[i].x && head.y === this.snake[i].y) {
          return true;
        }
      }

      return false;
    },
  },
};
</script>

<style scoped>
.snake-game {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background: #1a1a1a; /* Dark background */
  color: #ffffff; /* Light text color */
  font-family: Arial, sans-serif;
  position: relative;
}

.score-board {
  font-size: 32px;
  margin-bottom: 20px;
  background: rgba(255, 255, 255, 0.1);
  padding: 10px 20px;
  border-radius: 10px;
  text-align: center;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}

canvas {
  border: 4px solid #ffffff; /* White border */
  background-color: rgba(0, 0, 0, 0.1); /* Semi-transparent black background */
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
}

.game-over {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 32px;
  background-color: rgba(0, 0, 0, 0.8); /* Dark semi-transparent background */
  padding: 20px;
  border: 4px solid #ffffff; /* White border */
  border-radius: 10px;
  text-align: center;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
}

.controls {
  margin-top: 20px;
}

.controls button {
  margin: 0 10px;
  padding: 10px 20px;
  font-size: 16px;
  color: #ffffff;
  background-color: #333333;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.controls button:hover {
  background-color: #555555;
}

.controls button:disabled {
  background-color: #777777;
  cursor: not-allowed;
}
</style>